/**
 * websocket的服务类，主要用于连接服务器、接收消息等
 * 这个类所有的方法都是静态的
 */
Ext.define("WebsocketService",{
	socket:null,
	serverURL:"servlet/WebSocketServlet.socket",
	statics:{
		/**
		 * 检查浏览器是否支持websocket
		 * @return {boolean} 支持返回true，否则返回false
		 */
		checkSupport:function(){
			return window.WebSocket;
		},
		/**
		 * 连接服务器
		 */
		connect:function(){
			if(this.checkSupport()){
				var location = document.location.toString().replace('http://','ws://').replace('https://','wss://');
				location = location.substring(0,location.lastIndexOf("/"))+"/servlet/WebSocketServlet.socket";
				try{
					this.socket = new WebSocket(location);
					this.socket.onmessage=this.reviceMsg;
					this.socket.onclose = this.close;
					this.socket.onopen = this.success;
					this.socket.onerror = this.error;
				}catch(msg){
					Ext.Msg.alert("错误","连接服务器失败!");
				}
				return true;
			}
			return false;
		},
		/**
		 * 收到消息的回调函数
		 * 
		 */
		reviceMsg:function(m){
			var mess=null;
			try{
				console.log("收到消息："+m.data);
				mess = Ext.JSON.decode(m.data);
			}catch(msg){
				console.log("系统发送消息无法正常解析:"+m.data);
				return;
			}
			new MessageHandleService().handleMessage(mess);
		},
		/**
		 * 连接关闭的回调函数
		 */
		close:function(m){
			this.socket = null;
			if(WebsocketService.offline!=122&&WebsocketService.offline!=302){//如果为强制下线或者是自动下线就不允许出现提示
				new UserService().updateStatus(UserStatus.OFFLINE);
				Ext.Msg.alert("错误","与服务器断开连接");
			}
		},
		/**
		 * 连接成功的回调函数
		 */
		success:function(){
			new UserService().loadFriends();//加载好友
			WebsocketService.sendOnlineMsg(AppContext.getStatus());
		},
		/**
		 * 出错时的回调函数
		 */
		error:function(m){
			this.socket.close();
			this.socket = null;
			Ext.Msg.alert("错误","连接服务器失败!");
		},
		/**
		 * 发送上线消息的函数，这个方法只能调用一次
		 */
		sendOnlineMsg:function(status){
			this.socket.send(new MessageHandleService().handleMsgToJSON(301,0,status));
		},
		/**
		 * 发送下线消息
		 */
		sendOfflineMsg:function(){
			this.socket.send(new MessageHandleService().handleMsgToJSON(302,0,AppContext.getStatus()));
		},
		/**
		 * 发送更新状态的方法
		 */
		sendChangeStatusMsg:function(code,status){
			this.socket.send(new MessageHandleService().handleMsgToJSON(code,0,status));
		},
		sendShakeMsg:function(target){
			this.socket.send(new MessageHandleService().handleMsgToJSON(205,target,"shake"))
		},
		/**
		 * 发送消息的函数
		 * @param {long} target  目标的ID
		 * @param {string} msg 发送的消息内容
		 */
		sendMsg:function(target,msg){
			msg = Ext.htmlEncode(msg);
			if(this.socket==null){
				return false;
			}
			try{
				this.socket.send(new MessageHandleService().handleMsgToJSON(201,target,msg));
			}catch(msg){
				return false;
			}
			return true;
		}
	}
});

/**
 * 消息处理服务类
 */
Ext.define("MessageHandleService",{
	/**
	 * 获得当前系统时间
	 * @return {string} 
	 */
	getNowTime:function(){
		return Ext.Date.format(new Date(),"Y-m-d G:i:s");
	},
	/**
	 * 将消息格式化为标准JSON格式字符串
	 * @param status 状态码
	 * @param target 消息接收目标ID
	 * @param msg 需要发送的消息
	 * @return {string} json 
	 */
	handleMsgToJSON:function(status,target,msg){
		var json = "{\"status\":"+status+",\"from\":"+AppContext.getUID()+",\"time\":\""+this.getNowTime()+"\",\"target\":"+target+",\"msg\":\""+msg+"\"}";
		return json;
	},
	/**
	 * 格式化接收的消息
	 * @param {int} id 发送目标的ID
	 * @param {string} time 消息发送时间
	 * @param {string} msg 接收到的消息
	 */
	formatMsg:function(id,time,msg){
		msg =  Ext.htmlDecode(msg);
		return "&nbsp;<div style='clear:both;color:green;'>"+Ext.getCmp("cu_"+id).nickname+" "+time+"</div><div style='margin-left:15px;'>"+msg+"</div>";
	},
	formatSendMsg:function(time,msg){
		msg =  Ext.htmlDecode(msg);
		return "&nbsp;<div style='clear:both;color:blue;'>"+AppContext.getNickname()+" "+time+"</div><div style='margin-left:15px;'>"+msg+"</div>";
	},
	/**
	 * 处理消息
	 * @param {object} mess 收到的JSON消息
	 */
	handleMessage:function(mess){
		if(mess!=null){
			switch(mess["status"]){
				case MessageCode.USER_ONLINE:
					this.online(mess);
					break;
				case MessageCode.USER_OFFLINE:
					this.offline(mess);
					break;
				case MessageCode.USER_BUSY:
					this.busy(mess);
					break;
				case MessageCode.USER_AWAY:
					this.away(mess);
					break;
				case MessageCode.USER_INVISIBLE:
					this.invisible(mess);
					break;
				case MessageCode.USER_REONLINE:
					this.reonline(mess);
					break;
				case 122:
					this.otherSapce(mess);
					break;
				case 201:
					this.textMsg(mess);
					MessageService.playReviceMusic();
					break;
				case 205:
					this.shake(mess);
					MessageService.playShakeMusic();
					break;
				default:
					break;
			}
		}
	},
	/**
	 * 处理文本消息的函数
	 * @param {object} mess 消息的JSON对象
	 */
	textMsg:function(mess){
		var target = mess["from"];
		var msg =mess["msg"];
		var time = mess["time"];
		if(Ext.getCmp("cw_"+target)!=null&&!Ext.getCmp("cw_"+target).isHidden()){//如果收到的消息的发送用户的窗体已经显示了，那么直接推送消息
			var service = new MessageHandleService();
			Ext.getCmp("cw_"+target+"_rw").setText(document.getElementById("cw_"+target+"_rw").innerHTML+service.formatMsg(target,time,msg),false);
			Ext.get("cw_"+target+"_rw").scroll("bottom",document.getElementById("cw_"+target+"_rw").innerHTML.length,false);//滚动至底部
			Ext.get("cw_"+target+"_rw").scroll("right",document.getElementById("cw_"+target+"_rw").innerHTML.length,false);//滚动至左部
		}else{
			if(Ext.getCmp("cw_"+target+"_job")!=null){//如果窗体在任务栏下面
				var service = new MessageHandleService();
				Ext.getCmp("cw_"+target+"_rw").setText(document.getElementById("cw_"+target+"_rw").innerHTML+service.formatMsg(target,time,msg),false);
				Ext.get("cw_"+target+"_rw").scroll("bottom",document.getElementById("cw_"+target+"_rw").innerHTML.length,false);//滚动至底部
				Ext.get("cw_"+target+"_rw").scroll("right",document.getElementById("cw_"+target+"_rw").innerHTML.length,false);//滚动至左部
				var divId = Ext.get("cw_"+target+"_job").query("div")[0].id;//获得任务的label中的DIV
				new MessageService().blinkJob(divId);
			}else{//不在任务栏，那么就要创建消息提示
				if(Ext.getCmp("MSGWINDOW")==null){
					var win = new MsgNoticeWindow({floating:true,style:{backgroundColor:"white",border:"1px solid #759CA5"}});
					win.addNewMsg(mess,Ext.getCmp("cu_"+mess["from"]).icon,Ext.getCmp("cu_"+mess["from"]).nickname);
				}else{
					var win = Ext.getCmp("MSGWINDOW");
					win.addNewMsg(mess,Ext.getCmp("cu_"+mess["from"]).icon,Ext.getCmp("cu_"+mess["from"]).nickname);
				}
				noticeMsg(true);//开始提示信息
			}
		}
	},
	/**
	 * 处理上线消息的函数
	 * @param {object} mess 消息的JSON对象
	 */
	online:function(mess){//好友上线消息处理
		Ext.getCmp("cu_"+mess["msg"]).updateStatus(1);
		var gid = Ext.getCmp("cu_"+mess["msg"]).groupId;
		//var fp = Ext.getCmp("groupChild_"+gid).items.items;//获得一个分组下所有的好友容器
		//TODO 当一个好友上线时应将好友移动到前面
	},
	/**
	 * 处理用户下线的消息
	 * @param {object} mess 消息的JSON对象
	 */
	offline:function(mess){
		Ext.getCmp("cu_"+mess["msg"]).updateStatus(0);
		//TODO 当一个好友下线时应将他移动到好友列表后面
	},
	/**
	 * 处理当前用户被强制下线的消息
	 * @param {Object} mess 收到的消息
	 */
	otherSapce:function(mess){
		WebsocketService.offline = mess["status"];
		WebsocketService.socket.close();
		WebsocketService.socket = null;
		Ext.Msg.alert("警告","您的帐号在其它地点登录，请确认是否密码被盗!",function(btn){
			if(btn=="ok"){
				Ext.getCmp("listWindow").destroy();
				for(var i=0;i<AppContext.cwMap.length;i++){//销毁所有聊天窗口
					AppContext.cwMap[i].cw.destroy();						
				}
			}
		});
	},
	/**
	 * 收到消息为用户抖动
	 */
	shake:function(mess){
		var win = Ext.getCmp("cw_"+mess["from"]);
		if(win==null){
			ListWindowHandler.openChatWin(mess["from"],Ext.getCmp("cu_"+mess["from"]).nickname,"./img/info/"+Ext.getCmp("cu_"+mess["from"]).icon+"_m.jpg");
		}
		win = Ext.getCmp("cw_"+mess["from"]);
		win.show();
		shake("cw_"+mess["from"],0);
	},
	busy:function(mess){
		Ext.getCmp("cu_"+mess["msg"]).updateStatus(UserStatus.BUSY);
	},
	away:function(mess){
		Ext.getCmp("cu_"+mess["msg"]).updateStatus(UserStatus.AWAY);
	},
	invisible:function(mess){
		Ext.getCmp("cu_"+mess["msg"]).updateStatus(UserStatus.OFFLINE);
	},
	reonline:function(mess){
		Ext.getCmp("cu_"+mess["msg"]).updateStatus(UserStatus.ONLINE);
	}
});